package query_service

import (
	"context"
	"github.com/go-kratos/kratos/v2/log"
	"gotham-plan-manage/internal/app/convertor"
	"gotham-plan-manage/internal/domain/command"
	"gotham-plan-manage/internal/domain/repo"
	"gotham-plan-manage/internal/domain/service"
	"gotham-plan-manage/internal/infra/cache/redis/plan"
	"gotham-plan-manage/internal/infra/cache/redis/task"
	"gotham-plan-manage/pkg/dateutils"
	"gotham-plan-manage/pkg/jwt_util"
)

/*
   @author：zhongyang
   @date:2023/4/2
   @description: 计划管理-命令应用服务（增删改）
*/

type PlanManageCommandService struct {
	PlanDomainService *service.PlanManageDomainService
	PlanManageRepo    repo.PlanManageIRepo
	planConvertor     convertor.PlanManageConvertor
	tx                Transaction
	logger            *log.Helper
}

func NewPlanManageCommandService(planDomainService *service.PlanManageDomainService, planManageRepo repo.PlanManageIRepo, tx Transaction, logger log.Logger) *PlanManageCommandService {
	return &PlanManageCommandService{PlanDomainService: planDomainService, PlanManageRepo: planManageRepo, tx: tx, logger: log.NewHelper(logger)}
}

func (p *PlanManageCommandService) CreatePlan(ctx context.Context, command *command.PlanCreateCommand) error {
	// 将命令转换为聚合根
	planAggregate, err := p.planConvertor.CreatePlanAggregate(command.Name, command.StartDate, command.EndDate, command.ParentId)
	if err != nil {
		return err
	}
	// 计划实体执行创建计划的业务逻辑
	err = planAggregate.Create(ctx)
	if err != nil {
		return err
	}
	// 调用仓储层，做持久化操作
	err = p.tx.ExecTx(ctx, func(ctx context.Context) error {
		err = p.PlanManageRepo.CreatePlan(ctx, planAggregate)
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	// 2.发送领域事件到MQ
	return nil
}

func (p *PlanManageCommandService) DeletePlan(ctx context.Context, command *command.PlanDeleteCommand) error {
	// 获取聚合根
	planAggregate, err := p.PlanManageRepo.FindPlanById(ctx, command.PlanId)
	if err != nil {
		return err
	}
	err = p.tx.ExecTx(ctx, func(ctx context.Context) error {
		// 这里涉及多实体，考虑放到领域服务完成删除
		err = p.PlanDomainService.DeletePlan(ctx, planAggregate)
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) EditPlan(ctx context.Context, command *command.PlanEditCommand) error {
	planAggregate, err := p.PlanManageRepo.FindPlanById(ctx, command.PlanId)
	if err != nil {
		return err
	}
	// 聚合根完成编辑计划的业务逻辑
	err = planAggregate.Edit(command.Name, command.StartDate, command.EndDate, command.ParentId)
	if err != nil {
		return err
	}
	// 调用仓储层完成数据持久化
	err = p.PlanManageRepo.EditPlan(ctx, planAggregate)
	if err != nil {
		return err
	}
	// 发布计划更新事件给MQ

	return nil
}

func (p *PlanManageCommandService) EditTarget(ctx context.Context, editCommand *command.TargetEditCommand) error {
	planAggregate, err := p.PlanManageRepo.FindPlanContainsDetailById(ctx, editCommand.PlanID)
	if err != nil {
		return err
	}
	// 聚合根实现修改目标的业务逻辑
	err = planAggregate.EditTarget(editCommand.PlanID, editCommand.Target)
	if err != nil {
		return err
	}
	// 持久化操作
	err = p.PlanManageRepo.EditTarget(ctx, planAggregate)
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) SubmitPlanReport(ctx context.Context, submitCommand *command.PlanReportSubmitCommand) error {
	plan, err := p.PlanManageRepo.FindPlanById(ctx, submitCommand.PlanId)
	if err != nil {
		return err
	}
	plan.SubmitReport(submitCommand.RealDay, submitCommand.ExpectDay, submitCommand.IsOverTime, submitCommand.TaskTotal)
	// 调用仓储层完成持久化操作
	err = p.PlanManageRepo.SubmitPlanReport(ctx, plan)
	if err != nil {
		return err
	}
	return p.PlanManageRepo.FinishPlan(ctx, plan)
}

func (p *PlanManageCommandService) CreateTaskItem(ctx context.Context, command *command.CreateTaskCommand) error {
	plan, err := p.PlanManageRepo.FindPlanContainsTaskByPlanIdAndDate(ctx, command.PlanId, command.ExecuteDate)
	if err != nil {
		return err
	}
	// 通过聚合根完成领域业务逻辑
	plan.CreateTask(command.ExecuteDate, command.Content, command.Level)
	// 持久化操作
	err = p.tx.ExecTx(ctx, func(ctx context.Context) error {
		err = p.PlanManageRepo.CreateTask(ctx, plan)
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) DeleteTaskItemById(ctx context.Context, itemCommand *command.DeleteTaskItemCommand) error {
	// 这里后面可能涉及到要保证计划报告的完整性，所以这里可能不能直接进行删除操作
	return p.PlanManageRepo.DeleteTaskItem(ctx, itemCommand.TaskItemId)
}

func (p *PlanManageCommandService) DeleteTaskById(ctx context.Context, deleteTaskCommand *command.DeleteTaskCommand) error {
	err := p.tx.ExecTx(ctx, func(ctx context.Context) error {
		return p.PlanManageRepo.DeleteTask(ctx, deleteTaskCommand.TaskId)
	})
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) EditTaskItemById(ctx context.Context, editTaskItemCommand *command.EditTaskItemCommand) error {
	err := p.tx.ExecTx(ctx, func(ctx context.Context) error {
		return p.PlanDomainService.EditTaskItem(ctx, editTaskItemCommand.PlanId, editTaskItemCommand.Id, editTaskItemCommand.Level, editTaskItemCommand.Content, editTaskItemCommand.ExecuteDate)
	})
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) FinishTaskItem(ctx context.Context, itemCommand *command.FinishTaskItemCommand) error {
	plan, err := p.PlanManageRepo.GetTaskItemById(ctx, itemCommand.TaskItemId)
	if err != nil {
		return err
	}
	// 完成领域内的业务操作
	err = plan.FinishTaskItem()
	if err != nil {
		return err
	}
	err = p.PlanManageRepo.FinishTaskItem(ctx, plan)
	if err != nil {
		return err
	}
	// 周排行榜次数 + 1
	task.IncrTaskTotalFromTaskWeekRank(ctx, jwt_util.GetAccount(ctx))
	return nil
}

func (p *PlanManageCommandService) SaveQuestions(ctx context.Context, req *command.SaveQuestionCommand) error {
	plan, err := p.PlanManageRepo.FindOneDayQuestions(ctx, req.Questions[0].PlanId, req.Questions[0].TodoTaskDate)
	if err != nil {
		return err
	}
	deleteQuestions := plan.DeleteQuestions(req.Questions)
	err = p.tx.ExecTx(ctx, func(ctx context.Context) error {
		if len(deleteQuestions) != 0 {
			err := p.PlanManageRepo.BatchDeleteQuestions(ctx, deleteQuestions)
			if err != nil {
				return err
			}
		}
		plan.SaveQuestions(req.Questions, jwt_util.GetUserId(ctx))
		return p.PlanManageRepo.SaveQuestions(ctx, plan)
	})
	if err != nil {
		return err
	}
	return nil
}

func (p *PlanManageCommandService) SetExpectTaskTotal(ctx context.Context, totalCommand *command.SetExpectTaskTotalCommand) error {
	startDate, endDate := dateutils.WeekIntervalTime(1)
	key := plan.GeneratePlanReviewKey(totalCommand.PlanId, startDate, endDate)
	task.SetNextWeekTargetTaskItemTotal(ctx, key, string(totalCommand.NextWeekTargetFinishTotal))
	return nil
}
